/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session;

import event.SendEvent;
import event.StatusEvent;
import java.util.ArrayList;
import net.sf.appia.core.Direction;
import net.sf.appia.core.Event;
import net.sf.appia.core.Layer;
import net.sf.appia.core.events.channel.ChannelClose;
import net.sf.appia.core.events.channel.ChannelInit;
import net.sf.appia.protocols.common.RegisterSocketEvent;
import util.Debug;

/**
 *
 * @author Welington
 */
public class PerfectLinkSession extends CustomSession{
    private ArrayList<SendEvent> delivered = new ArrayList<SendEvent>();
    
    public PerfectLinkSession(Layer layer) {
        super(layer);
        current = getClass();
    }
    
    @Override
    public void handle(Event event) {
        if (event instanceof ChannelInit) {
            handleInit((ChannelInit) event);
        } else if (event instanceof ChannelClose) {
            handleCloseChannel((ChannelClose) event);
        } else if (event instanceof SendEvent) {
            if (event.getDir() == Direction.UP)
                handleDeliveryEvent((SendEvent) event);
            else
                handleSendEvent((SendEvent) event);
        } else if (event instanceof RegisterSocketEvent) {
            handleRegisterSocket((RegisterSocketEvent) event);
        } else if (event instanceof StatusEvent) {
            handleStatusEvent((StatusEvent) event);
        }
    }
    
    /**
     * upon event <pl, Init> do
     *      delivered := ∅;
     * @param event 
     */
    @Override
    protected void handleInit(ChannelInit event) {
        debug.print(Debug.LOG, current, "handleInit(ChannelInit event)");
        sendEvent(event);
        delivered.clear();
     }
     
     private void handleCloseChannel(ChannelClose event) {
        debug.print(Debug.LOG, current, "handleCloseChannel(ChannelClose event)");
        sendEvent(event);
    }
    
    /**
      * upon event <sl, Deliver | p, m> do
      *     if m not(∈) delivered then
      *         delivered := delivered ∪ {m};
      *         trigger <pl, Deliver | p, m>;
      * @param event 
      */
    private void handleDeliveryEvent(SendEvent event) {
        debug.print(Debug.LOG, current, "handleDeliveryEvent(DeliveryEvent event)");
        
        if (!delivered.contains(event)) {
            delivered.add(event);
            sendEvent(event);
        }
    }
    
    private void handleRegisterSocket(RegisterSocketEvent event) {
        debug.print(Debug.LOG, current, "handleRegisterSocket(RegisterSocketEvent event)");
        sendEvent(event);
    }
    
    private void handleSendEvent(SendEvent event) {
        debug.print(Debug.LOG, current, "handleSendEvent(SendEvent event)");
        sendEvent(event);
    }
    
    private void handleStatusEvent(StatusEvent event) {
        debug.print(Debug.LOG, current, "handleStatusEvent(StatusEvent event)");
        sendEvent(event);
    }
}
